package org.moyu.handler;

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.moyu.response.ResponseData;
import org.moyu.response.SuccessResponseData;
import org.springframework.core.MethodParameter;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.lang.Nullable;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.lang.annotation.Annotation;

/**
 * 响应拦截器，统一响应格式
 * 如果响应接口被 @NotResponseData 注解，则不进行拦截，直接返回
 */

@Slf4j
@ControllerAdvice
public class ResponseHandler implements ResponseBodyAdvice<Object> {
    private static final Class<? extends Annotation> ANNOTATION_TYPE = NotResponseData.class;


    private boolean hasResponseResultBodyAnnotation(MethodParameter returnType) {
        return AnnotatedElementUtils.hasAnnotation(returnType.getContainingClass(), ANNOTATION_TYPE) ||
                returnType.hasMethodAnnotation(ANNOTATION_TYPE);
    }

    @Override
    public boolean supports(@Nullable MethodParameter returnType, @Nullable Class<? extends HttpMessageConverter<?>> converterType) {
        return returnType == null || !hasResponseResultBodyAnnotation(returnType);
    }

    @SneakyThrows
    @Override
    public Object beforeBodyWrite(Object body, @Nullable MethodParameter returnType, @Nullable MediaType selectedContentType,
                                  @Nullable Class<? extends HttpMessageConverter<?>> selectedConverterType, @Nullable ServerHttpRequest request,
                                  @Nullable ServerHttpResponse response) {
        // 如果返回类型是ResponseData，直接返回
        if (body instanceof ResponseData) {
            return body;
        }

        return new SuccessResponseData(body);
    }
}
